package com.ming.sevice.impl;

import com.alibaba.fastjson.JSON;
import com.ming.constant.MenuConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ming.domain.SysMenu;
import com.ming.mapper.SysMenuMapper;
import com.ming.sevice.SysMenuService;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

/**
 *@Author:何元才
 *@Desc:
 *@data:2021-03-31 15:24
 */
@Service
@Slf4j
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService{


    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 根据用户id查询菜单
     *
     * 这里需要用到缓存
     * redis的菜单就是单纯的list 树形结构 在代码中
     * 1.先判断缓存有没有
     * 2.缓存没有再查询 放入缓存
     * 3.组装菜单
     *
     * @param sysUserId
     * @return
     */
    @Override
    public List<SysMenu> findUserMenu(Long sysUserId) {
        //查询缓存有没有当前用户菜单
        String menuStr = redisTemplate.opsForValue().get(MenuConstant.MENU_PREFIX + sysUserId);
        List<SysMenu> menus = null;
        if(StringUtils.hasText(menuStr)) {
            //转一下
            menus = JSON.parseArray(menuStr,SysMenu.class);
        } else {
            //查询 存进去
            menus = sysMenuMapper.findSysUserMenu(sysUserId);
            if(!CollectionUtils.isEmpty(menus)){
                //转json放进去 redis设置一个过期时间
                redisTemplate.opsForValue().set(MenuConstant.MENU_PREFIX+sysUserId,JSON.toJSONString(menus), Duration.ofDays(7));
            }
        }
        //转换树形菜单
        return translateTree(menus,0L);
    }

    /**
     * 转化树形菜单
     *
     * @param menus
     * @param pid
     * @return
     */
    private List<SysMenu> translateTree(List<SysMenu> menus, long pid) {
        //1.根据菜单深度来选择 组装方式 双重for
        //2.拿到顶级菜单
        List<SysMenu> root = menus.stream()
                .filter(sysMenu -> sysMenu.getParentId().equals(pid))
                .collect(Collectors.toList());
        //3.循环顶级菜单 匹配子菜单
         root.forEach(r->{
             //循环所有菜单
             List<SysMenu> child = menus.stream()
                     .filter(sysMenu -> sysMenu.getParentId().equals(r.getMenuId()))
                     .collect(Collectors.toList());
             r.setList(child);
         });
         return root;
    }
}
